/*
 * JstpwPanel.java
 *
 * Created on 21 March 2007, 14:43
 */

package jstpw;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.DefaultListModel;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author  ser
 */
public class JstpwPane extends javax.swing.JPanel implements ListSelectionListener {
    
    private final static int UNSET = -1;
    
    final TimeUpdater updater = new TimeUpdater();
    final javax.swing.Timer timer = new javax.swing.Timer(100, updater);
    final DefaultListModel history = new DefaultListModel();
    final TimesTableModel storage = new TimesTableModel();
    final DumpFrame dumpFrame = new DumpFrame();
    int currentRow = UNSET;
    long timeOnStopwatch;
    long startTime;
    boolean stopped = true;
    
    public TimesTableModel getModel() {
        return storage;
    }
    
    /** Creates new form JstpwPanel */
    public JstpwPane() {
        initComponents();
        storedTimesTable.setDefaultRenderer(Long.class, new TimeRenderer());
        storedTimesTable.getSelectionModel().addListSelectionListener(this);
        storedTimesTable.getColumn(Long.class).getHeaderRenderer();
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jSplitPane = new javax.swing.JSplitPane();
        jPanel = new javax.swing.JPanel();
        timeEntry = new javax.swing.JTextField();
        startButton = new javax.swing.JToggleButton();
        stopButton = new javax.swing.JButton();
        stampButton = new javax.swing.JButton();
        jScrollPaneH = new javax.swing.JScrollPane();
        historyList = new javax.swing.JList(history);
        jPanel1 = new javax.swing.JPanel();
        jScrollPaneS = new javax.swing.JScrollPane();
        storedTimesTable = new javax.swing.JTable();
        dumpButton = new javax.swing.JButton();
        deleteButton = new javax.swing.JButton();

        setLayout(new java.awt.BorderLayout());

        setBackground(new java.awt.Color(255, 255, 255));
        jSplitPane.setDividerSize(5);
        jSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        jSplitPane.setResizeWeight(0.5);
        jPanel.setLayout(new java.awt.GridBagLayout());

        timeEntry.setBackground(new java.awt.Color(255, 255, 255));
        timeEntry.setEditable(false);
        timeEntry.setFont(timeEntry.getFont().deriveFont(timeEntry.getFont().getStyle() | java.awt.Font.BOLD, timeEntry.getFont().getSize()+12));
        timeEntry.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        timeEntry.setText("00:00:00.0");
        timeEntry.setName("timeEntry");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        jPanel.add(timeEntry, gridBagConstraints);

        startButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/jstpw/img/player_play.png")));
        startButton.setToolTipText("Start/Pause");
        startButton.setFocusPainted(false);
        startButton.setName("startButton");
        startButton.setSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/jstpw/img/player_pause.png")));
        startButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startButtonActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        jPanel.add(startButton, gridBagConstraints);

        stopButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/jstpw/img/player_stop.png")));
        stopButton.setToolTipText("Reset counter and store in history list");
        stopButton.setFocusPainted(false);
        stopButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopButtonActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.weightx = 1.0;
        jPanel.add(stopButton, gridBagConstraints);

        stampButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/jstpw/img/add.png")));
        stampButton.setFocusPainted(false);
        stampButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stampButtonActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        jPanel.add(stampButton, gridBagConstraints);

        historyList.setFont(historyList.getFont().deriveFont(historyList.getFont().getStyle() & ~java.awt.Font.BOLD, historyList.getFont().getSize()+4));
        historyList.setForeground(new java.awt.Color(153, 153, 153));
        jScrollPaneH.setViewportView(historyList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPanel.add(jScrollPaneH, gridBagConstraints);

        jSplitPane.setLeftComponent(jPanel);

        jPanel1.setLayout(new java.awt.GridBagLayout());

        jScrollPaneS.setAutoscrolls(true);
        storedTimesTable.setForeground(new java.awt.Color(102, 102, 102));
        storedTimesTable.setModel(getModel());
        storedTimesTable.setGridColor(new java.awt.Color(204, 204, 204));
        jScrollPaneS.setViewportView(storedTimesTable);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPanel1.add(jScrollPaneS, gridBagConstraints);

        dumpButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/jstpw/img/mail_new.png")));
        dumpButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dumpButtonActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        jPanel1.add(dumpButton, gridBagConstraints);

        deleteButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/jstpw/img/edit-delete.png")));
        deleteButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                deleteButtonActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        jPanel1.add(deleteButton, gridBagConstraints);

        jSplitPane.setBottomComponent(jPanel1);

        add(jSplitPane, java.awt.BorderLayout.CENTER);

    }// </editor-fold>//GEN-END:initComponents

    private void dumpButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dumpButtonActionPerformed
        StringBuilder buff = new StringBuilder();
        buff.append("<pre>\n");
        for (Object ro:storage.getDataVector()) {
            Vector row = (Vector)ro;
            String name = row.get(1) == null ? "" : (String)row.get(1);
            buff.append("\t").append(formatAsTimeText((Long)row.get(0))).append("\t")
                    .append(name).append("\n");
        }
        buff.append("</pre>\n");
        dumpFrame.dumpEditorPane.setText(buff.toString());
        dumpFrame.setVisible(true);
    }//GEN-LAST:event_dumpButtonActionPerformed

    private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteButtonActionPerformed
        if (currentRow != UNSET) {
            int tmpRow = currentRow - 1;
            storage.getDataVector().remove(currentRow);
            storage.fireTableRowsDeleted(currentRow, currentRow);
            if (tmpRow < 0) {
                tmpRow = 0;
            }
            storedTimesTable.getSelectionModel().setSelectionInterval(tmpRow, tmpRow);
        }
    }//GEN-LAST:event_deleteButtonActionPerformed

    private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startButtonActionPerformed
        if (startButton.isSelected()) {
            if (stopped) {
                stopped = false;
                timeOnStopwatch = 0;
            }
            startTime = getCurrentTime();
            timer.start();
        } else {
            timer.stop();
            storeTimeInHistoryList();
        }
    }//GEN-LAST:event_startButtonActionPerformed

    private void stampButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stampButtonActionPerformed
        storage.insertRow(0, new Object[] {timeOnStopwatch, null});
        storage.fireTableRowsInserted(0,0);
        storedTimesTable.getSelectionModel().setSelectionInterval(0,0);
    }//GEN-LAST:event_stampButtonActionPerformed

    private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stopButtonActionPerformed
        if (startButton.isSelected()) {
            startButton.doClick();
        }
        stopped = true;
        storedTimesTable.getSelectionModel().clearSelection();
    }//GEN-LAST:event_stopButtonActionPerformed
    
    public void valueChanged(ListSelectionEvent e) {
        if (e.getValueIsAdjusting()) return;

        ListSelectionModel lsm = (ListSelectionModel)e.getSource();
        
        if (lsm.isSelectionEmpty()) {
            currentRow = UNSET;
        } else {
            int newRow = lsm.getLeadSelectionIndex();
            if (newRow >= storage.getDataVector().size()) {
                return;
            }
            if (newRow != currentRow) {
                currentRow = newRow;
                timeOnStopwatch = (Long)((Vector)storage.getDataVector().get(currentRow)).get(0);
                timeEntry.setText(formatAsTimeText(timeOnStopwatch));
                stopped = false;
            }
        }
    }
    
    private void storeTimeInHistoryList() {
        history.add(0, timeEntry.getText());
    }

    private void storeTimeInStorage() {
        if (currentRow != UNSET) {
            Vector row = (Vector)storage.getDataVector().get(currentRow);
            row.set(0, timeOnStopwatch);
            storage.fireTableCellUpdated(currentRow,0);
        }
    }

    private long getCurrentTime() {
        return System.currentTimeMillis() / 100;
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton deleteButton;
    private javax.swing.JButton dumpButton;
    private javax.swing.JList historyList;
    private javax.swing.JPanel jPanel;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPaneH;
    private javax.swing.JScrollPane jScrollPaneS;
    private javax.swing.JSplitPane jSplitPane;
    private javax.swing.JButton stampButton;
    private javax.swing.JToggleButton startButton;
    private javax.swing.JButton stopButton;
    private javax.swing.JTable storedTimesTable;
    private javax.swing.JTextField timeEntry;
    // End of variables declaration//GEN-END:variables
    
    public static String formatAsTimeText(long time) {
        long h;
        long m;
        long s;
        long ss;
        
        ss = time % 10;
        s = time / 10;
        m = s / 60;
        s = s % 60;
        h = m / 60;
        m = m % 60;
        
        return String.format("%02d:%02d:%02d.%d", h, m, s, ss);
    }

    class TimesTableModel extends DefaultTableModel {
        
        Class[] types = new Class [] {
            java.lang.Long.class,
            java.lang.String.class
        };
        
        public TimesTableModel() {
            this.addColumn("Time");
            this.addColumn("Name");
        }
        
        boolean[] canEdit = new boolean [] {
            false, true
        };
        
        public Class getColumnClass(int columnIndex) {
            return types [columnIndex];
        }
        
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return canEdit [columnIndex];
        }
    }
    
    class TimeUpdater implements ActionListener {
        
        public void actionPerformed(ActionEvent actionEvent) {
            long currentTime = getCurrentTime();
            timeOnStopwatch += currentTime - startTime;
            startTime = currentTime;
            timeEntry.setText(formatAsTimeText(timeOnStopwatch));
            storeTimeInStorage();
        }
        
    }
    
    class TimeRenderer extends DefaultTableCellRenderer {
        
        public TimeRenderer() {
            super();
        }
        
        public void setValue(Object value) {
            setText(formatAsTimeText((Long)value));
        }
    }
}

